package com.hxzy.config.interceptor.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hxzy.common.annon.RepeatSubmit;
import com.hxzy.common.util.HttpHelper;
import com.hxzy.config.filter.RepeatedlyRequestWrapper;
import com.hxzy.config.interceptor.AbstractRepeatSubmitInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 自定义redis验证是否重复提交
 */
@Component
public class RedisRepeatSubmit extends AbstractRepeatSubmitInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * hash字段，存储参数
     */
    public final String REPEAT_PARAMS = "repeatParams";
    /**
     * hash字段，存储提交时间
     */
    public final String REPEAT_TIME = "repeatTime";

    @Override
    protected boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit repeatSubmit) {
        //当前参数
        String nowParam="";

        //读取参数 ( form body  json数据   POST/PUT [content-type:application/json])
        if(request instanceof RepeatedlyRequestWrapper){
            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
            nowParam= HttpHelper.getBodyString(repeatedlyRequest);
        }

        //提交数据从流中读不到,再看一看它的参数在不在  请求参数中 (post[content-type: application/x-www-form-urlencoded]   ,get)
        // request.getParameter()
        if(StrUtil.isBlank(nowParam)){
            nowParam= JSONUtil.toJsonStr( request.getParameterMap());
        }

        String token=request.getHeader("Authorization");
        //构造 redis的key (必须唯一，不能使用UUID)   前缀:url地址:自己【令牌,现在只有模拟】
        String redisKey="repeat_submit:"+ request.getRequestURI()+":"+token;

        long nowTime= new Date().getTime();

        //hash
        //有可能是重复提交的
        if(this.redisTemplate.hasKey(redisKey)){
            //if (本次时间-redis时间 < repeatSubmit.interval() &&  redis值==本次值)\
            long redisTime= (long) this.redisTemplate.opsForHash().get(redisKey,REPEAT_TIME);
            String redisParam=this.redisTemplate.opsForHash().get(redisKey,REPEAT_PARAMS).toString();
            if(nowTime-redisTime< repeatSubmit.interval() && nowParam.equals(redisParam)){
                return true;
            }
        }

        //重新写入值
        this.redisTemplate.opsForHash().put(redisKey,REPEAT_PARAMS, nowParam);
        this.redisTemplate.opsForHash().put(redisKey,REPEAT_TIME, nowTime);
        this.redisTemplate.expire(redisKey, repeatSubmit.interval(), TimeUnit.MILLISECONDS);

        return false;
    }
}
